<!DOCTYPE html>
<html>

<head>
    <title>cannon.js - hinge demo</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/style.css" type="text/css" />
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
    <script src="../../feng3d/out/feng3d.js"></script>
    <script src="../out/cannon.js"></script>
    <script src="../build/cannon.demo.js"></script>
    <script src="../libs/dat.gui.js"></script>
    <script src="../libs/Three.js"></script>
    <script src="../libs/TrackballControls.js"></script>
    <script src="../libs/Detector.js"></script>
    <script src="../libs/Stats.js"></script>
    <script src="../libs/smoothie.js"></script>
    <script>

        /**
         * Demonstrates how to use the HingeConstraint.
         * A hinge constraint makes sure that two bodies can rotate around a common axis. For example, think of a door hinge.
         */

        var demo = new CANNON.Demo();
        var mass = 1;

        demo.addScene("car", function ()
        {
            var world = demo.getWorld();
            world.gravity.set(0, 0, -20);

            var groundMaterial = new CANNON.Material("groundMaterial");
            var wheelMaterial = new CANNON.Material("wheelMaterial");
            var wheelGroundContactMaterial = new CANNON.ContactMaterial(groundMaterial, wheelMaterial, { friction: 0.5, restitution: 0.3 });
            world.addContactMaterial(wheelGroundContactMaterial);

            var wheelShape = new CANNON.Sphere(1.2);
            var leftFrontWheel = new CANNON.Body({ mass: mass, material: wheelMaterial });
            leftFrontWheel.addShape(wheelShape);
            var rightFrontWheel = new CANNON.Body({ mass: mass, material: wheelMaterial });
            rightFrontWheel.addShape(wheelShape);
            var leftRearWheel = new CANNON.Body({ mass: mass, material: wheelMaterial });
            leftRearWheel.addShape(wheelShape);
            var rightRearWheel = new CANNON.Body({ mass: mass, material: wheelMaterial });
            rightRearWheel.addShape(wheelShape);

            var chassisShape = new CANNON.Box(new CANNON.Vector3(5, 2, 0.5));
            var chassis = new CANNON.Body({ mass: mass });
            chassis.addShape(chassisShape);

            // Position constrain wheels
            var zero = new CANNON.Vector3();
            leftFrontWheel.position.set(5, 5, 0);
            rightFrontWheel.position.set(5, -5, 0);
            leftRearWheel.position.set(-5, 5, 0);
            rightRearWheel.position.set(-5, -5, 0);

            // Constrain wheels
            var constraints = [];

            // Hinge the wheels
            var leftAxis = new CANNON.Vector3(0, 1, 0);
            var rightAxis = new CANNON.Vector3(0, -1, 0);
            var leftFrontAxis = new CANNON.Vector3(0, 1, 0);
            var rightFrontAxis = new CANNON.Vector3(0, -1, 0);
            if (true)
            {
                leftFrontAxis = new CANNON.Vector3(0.3, 0.7, 0);
                rightFrontAxis = new CANNON.Vector3(-0.3, -0.7, 0);
                leftFrontAxis.normalize();
                rightFrontAxis.normalize();
            }

            constraints.push(new CANNON.HingeConstraint(chassis, leftFrontWheel, { pivotA: new CANNON.Vector3(5, 5, 0), axisA: leftFrontAxis, pivotB: zero, axisB: leftAxis }));
            constraints.push(new CANNON.HingeConstraint(chassis, rightFrontWheel, { pivotA: new CANNON.Vector3(5, -5, 0), axisA: rightFrontAxis, pivotB: zero, axisB: rightAxis }));
            constraints.push(new CANNON.HingeConstraint(chassis, leftRearWheel, { pivotA: new CANNON.Vector3(-5, 5, 0), axisA: leftAxis, pivotB: zero, axisB: leftAxis }));
            constraints.push(new CANNON.HingeConstraint(chassis, rightRearWheel, { pivotA: new CANNON.Vector3(-5, -5, 0), axisA: rightAxis, pivotB: zero, axisB: rightAxis }));

            for (var i = 0; i < constraints.length; i++)
                world.addConstraint(constraints[i]);

            var bodies = [chassis, leftFrontWheel, rightFrontWheel, leftRearWheel, rightRearWheel];
            for (var i = 0; i < bodies.length; i++)
            {
                world.addBody(bodies[i]);
                demo.addVisual(bodies[i]);
            }

            // Ground
            var groundShape = new CANNON.Plane();
            var ground = new CANNON.Body({ mass: 0, material: groundMaterial });
            ground.addShape(groundShape);
            ground.position.z = -3;
            world.addBody(ground);
            demo.addVisual(ground);

            // Enable motors and set their velocities
            var frontLeftHinge = constraints[2];
            var frontRightHinge = constraints[3];
            frontLeftHinge.enableMotor();
            frontRightHinge.enableMotor();
            var v = -14;
            frontLeftHinge.setMotorSpeed(v);
            frontRightHinge.setMotorSpeed(-v);

        });


        demo.addScene("hinge", function ()
        {
            var world = demo.getWorld();
            world.gravity.set(0, 5, -20);

            var s = 5, d = 0.1 * s;
            var shape = new CANNON.Box(new CANNON.Vector3(s * 0.5, s * 0.1, s * 0.5));
            var body = new CANNON.Body({ mass: mass });
            body.addShape(shape);
            var staticBody = new CANNON.Body({ mass: 0 });
            staticBody.addShape(shape);
            staticBody.position.z = s + d * 2;

            // Hinge it
            var c = new CANNON.HingeConstraint(staticBody, body, {
                pivotA: new CANNON.Vector3(0, 0, -s * 0.5 - d),
                axisA: new CANNON.Vector3(1, 0, 0),
                pivotB: new CANNON.Vector3(0, 0, s * 0.5 + d),
                axisB: new CANNON.Vector3(1, 0, 0)
            });
            world.addConstraint(c);

            world.addBody(body);
            world.addBody(staticBody);
            demo.addVisual(body);
            demo.addVisual(staticBody);
        });

        demo.start();

    </script>
</body>

</html>